package com.hongxin.nw.netty.utils;

import com.hongxin.nw.netty.model.packing.APCI;
import com.hongxin.nw.netty.model.packing.ASDU;
import com.hongxin.nw.netty.values.StaticValue;
import com.hongxin.nw.netty.values.TypeIdentif;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @remark 将数据封装成协议格式(南网协议)
 * @author: GuoXiaolin
 * @date 2019/6/17 15:09
 * @Version 1.0
 * @Descibe
 */
public class FieldPack {

    /**
     * 七个八位位组二进制时间 CP56 {毫秒，分，时，日，月，年（年—2000）}。
     */
    private static String getCP56Time(String format) {
        String[] s = format.split("-");

        String sss = String.valueOf((Integer.parseInt(s[5])*1000) + Integer.parseInt(s[6]));

        String ms = FieldPack.caseToBin(sss, TypeIdentif.BYTE_MS.getByteLength());
        String min = FieldPack.caseToBin(s[4], TypeIdentif.BYTE_MIN.getByteLength());
        String hours = FieldPack.caseToBin(s[3], TypeIdentif.BYTE_HOURS.getByteLength());
        String day = FieldPack.caseToBin(s[2], TypeIdentif.BYTE_DAY.getByteLength());
        String mouth = FieldPack.caseToBin(String.valueOf(Integer.valueOf(s[1])), TypeIdentif.BYTE_MOUTH.getByteLength());
        String year = FieldPack.caseToBin(String.valueOf(Integer.valueOf(s[0])-2000), TypeIdentif.BYTE_YEAR.getByteLength());

        return ms + min + hours + day + mouth + year;
    }

    //时间
    public static String caseTime(String str){
//        str = DateUtil.timeStamp2Date(str, "yyyy-MM-dd-HH-mm-ss-SSS");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
        str = sdf.format(new Date(Long.valueOf(str)));
        return  getCP56Time(str);
    }

    /**
     * 说明: 转bin格式
     * 1:先转十六进制
     * 2:高位补零
     * 3:字符串高低位转换
     * @param str 字符串
     * @param length 长度
     * @return 返回
     */
    public static String caseToBin(String str, Integer length){
        return BinaryTools.converter(BinaryTools.addZero(Integer.toHexString(Integer.parseInt(str)), length, StaticValue.DIRECTION_LEFT));
    }

    /**
     * 说明: 转BCD格式
     * 1:高位补零
     * 2:字符串高低位转换
     * @param str 字符串
     * @param length 长度
     * @return 返回
     */
    public static String caseToBCD(String str, Integer length){
        return BinaryTools.converter(BinaryTools.addZero(str, length, StaticValue.DIRECTION_LEFT));
    }

    /**
     *说明: 转字符格式
     * @param vin vin
     * @param length 长度
     * @return 返回
     */
    public static String caseToVin(String vin, Integer length){
        byte[] bb = vin.getBytes();
        return BinaryTools.addZero(BinaryTools.bytesToHexString(bb).toLowerCase(), length, StaticValue.DIRECTION_LEFT);
    }

    /**
     * 最高位：0：成功；1：失败
     * 低7位：失败原因
     * 1:SM4密钥错误
     * 127:其它原因
     * @param str 0:成功,1:SM4密钥错误,2:其它失败原因
     * @param length 长度
     * @return 返回
     */
    public static String caseToSuccess(int str, Integer length){
        String ss=String.valueOf(0b00000000);
        if (str==0){
            ss = String.valueOf(0b00000000);//成功
        }
        if (str==1){
            ss = String.valueOf(0b00000011);//SM4密钥错误
        }
        if (str==2){
            ss = String.valueOf(0b11111111);//其它失败原因
        }
        return BinaryTools.addZero(ss, length, StaticValue.DIRECTION_LEFT);
    }

    /**
     *
     * 精确到小数后 w 位转16进制,
     * @param num 值
     * @param w 小数点后多少位
     * @param length bin长度
     * @return 返回4字节
     */
    public static String decimalToHex(Double num, Integer w, Integer length) {
        BigDecimal temp = BigDecimal.valueOf(num);
        if (w == 5){
            //精确到小数后5位 将temp乘以100000
            temp = temp.multiply(BigDecimal.valueOf(100000));
        }
        if (w == 2){
            // 精确到小数后2位 将temp乘以100
            temp = temp.multiply(BigDecimal.valueOf(100));
        }
        if (w == 1){
            //精确到小数后1位 将temp乘以10
            temp = temp.multiply(BigDecimal.valueOf(10));
        }
        return caseToBCD(Integer.toHexString(temp.intValue()), length);
    }
    /**
     * ip字符串转十六进制字符串
     * AA...AA：FTP服务器IP(4字节HEX码);如：C0 02 03 04 表示IP为192.2.3.4；
     */
    public static String ip2hex(String ip){
        StringBuilder sb = new StringBuilder();
        String[] s = ip.split("\\.");
        for (String s1 : s) {
            String h = caseToBin(s1, TypeIdentif.BYTE_IP.getByteLength());
            sb.append(h);
        }
        return sb.toString();
    }

    /**
     * 端口转十六进制字符串
     * BBBB：端口号(1字节HEX码)；15 表示端口号21；
     */
    public static String port2hex(String port){
        return caseToBin(port, TypeIdentif.BYTE_PORT.getByteLength());
    }

    /**
     * 用户名转十六进制字符串
     * CC...CC：FTP用户名(10字节HEX码，00表示字符串结束)
     */
    public static String username2hex(String um){
        return caseToBin(um,TypeIdentif.BYTE_USERNAME.getByteLength()-2) + "00";
    }

    /**
     * 密码转十六进制字符串
     * DD...DD：FTP密码(10字节HEX码，00表示字符串结束)；
     */
    public static String pass2hex(String pass){
        return caseToBin(pass,TypeIdentif.BYTE_PASSWORD.getByteLength()-2) + "00";
    }

    /**
     * 路径转十六进制字符串
     * EE...EE：FTP路径(50字节HEX码，00表示字符串结束)；
     */
    public static String path2hex(String path){
        return caseToBin(path,TypeIdentif.BYTE_PATH.getByteLength()-2) + "00";
    }

    /**
     * 文件名转十六进制字符串
     * FF...FF：FTP文件名(50字节HEX码，00表示字符串结束)；
     */
    public static String file2hex(String file){
        return caseToBin(file,TypeIdentif.BYTE_FILENAME.getByteLength()-2) + "00";
    }

    /**
     * 厂家编码转十六进制字符串
     * GG...GG：厂家编码(10字节HEX码，00表示字符串结束)；
     */
    public static String code2hex(String code){
        return caseToBin(code,TypeIdentif.BYTE_FACTORY_CODE.getByteLength()-2) + "00";
    }

    /**
     * 硬件版本号转十六进制字符串
     * HH...HH：充电设备升级硬件版本号(30字节HEX码，00表示字符串结束)；
     */
    public static String hv2hex(String hv){
        return caseToBin(hv,TypeIdentif.BYTE_HARD_VERSION.getByteLength()-2) + "00";
    }

    /**
     * 软件版本号转十六进制字符串
     * KK...KK：充电设备升级软件版本号(20字节HEX码，00表示字符串结束)。
     */
    public static String sv2hex(String sv){
        return caseToBin(sv,TypeIdentif.BYTE_SOFTWARE_VERSION.getByteLength()-2) + "00";
    }

    /**
     * 获取APCI
     * @return 返回
     */
    public static String packAPCI(int length, String format, int info) throws Exception {
        APCI ac = new APCI();
        ac = ac.setIdentifyStart(TypeIdentif.IDENTIFY_START.getInt())
                .setAPDULength(length/2 + 4)
                .setConArea(format, info);
        return ac.getHexData();
    }

    /**
     * 获取ASDU
     * @return 返回
     */
    public static String packASDU(int identify,int cot, String statAddr, int infoAdr, int vsq, int sq){
        ASDU as = new ASDU();
        as.setType(identify);
        as.setCot(cot);
        as.setStaadr(statAddr);
        as.setInfoadr(infoAdr);
        as.setVsq(vsq, sq);
        return as.getHexData();
    }

}
